home *** CD-ROM | disk | FTP | other *** search
- /*********************************************************************
- Project : MacPerl - Real Perl Application
- File : MPFile.c -
- Author : Matthias Neeracher
-
- A lot of this code is borrowed from 7Edit written by
- Apple Developer Support UK
-
- Language : MPW C
-
- $Log: MPFile.c,v $
- Revision 1.1 1994/02/27 23:00:47 neeri
- Initial revision
-
- Revision 0.6 1993/09/17 00:00:00 neeri
- Runtime version
-
- Revision 0.5 1993/08/28 00:00:00 neeri
- Handle multiple preference files
-
- Revision 0.4 1993/08/17 00:00:00 neeri
- Enable Save
-
- Revision 0.3 1993/08/13 00:00:00 neeri
- Write bounds rectangles
-
- Revision 0.2 1993/05/30 00:00:00 neeri
- Support Console Windows
-
- Revision 0.1 1993/05/29 00:00:00 neeri
- Compiles correctly
-
- *********************************************************************/
-
- #include <Errors.h>
- #include <Resources.h>
- #include <Desk.h>
- #include <PLStringFuncs.h>
- #include <AppleEvents.h>
- #include <AERegistry.h>
- #include <StandardFile.h>
- #include <TFileSpec.h>
-
- #include "MPFile.h"
- #include "MPSave.h"
-
- /**-----------------------------------------------------------------------
- Name: FileError
- Purpose: Puts up an error alert.
- -----------------------------------------------------------------------**/
-
-
- #pragma segment File
-
- pascal void FileError(Str255 s, Str255 f)
- {
- short alertResult;
-
- SetCursor(&qd.arrow);
- ParamText(s, f, "", "");
- alertResult = Alert(ErrorAlert, nil);
- }
-
- /**-----------------------------------------------------------------------
- Name: DoClose
- Purpose: Closes a window.
- -----------------------------------------------------------------------**/
-
- #pragma segment File
-
- pascal OSErr DoClose(WindowPtr aWindow, Boolean canInteract, DescType dialogAnswer)
- {
- DPtr aDocument;
- short alertResult;
- Str255 theName;
- OSErr myErr;
-
- myErr = noErr;
-
- if (gWCount > 0) {
- aDocument = DPtrFromWindowPtr(aWindow);
-
- if (aDocument->kind == kDocumentWindow) {
- if (aDocument->dirty)
- if (canInteract && (dialogAnswer==kAEAsk)) {
- if (aDocument->u.reg.everSaved == false)
- GetWTitle(aWindow, theName); /* Pick it up as a script may have changed it */
- else
- PLstrcpy(theName, aDocument->theFileName);
-
- ParamText(theName, "", "", "");
- SetCursor(&qd.arrow);
- alertResult = Alert(SaveAlert, nil);
- switch (alertResult) {
- case aaSave:
- myErr = SaveAskingName(aDocument, canInteract);
- break;
-
- case aaCancel:
- return userCanceledErr;
-
- case aaDiscard:
- aDocument->dirty = false;
- break;
- }
- } else {
- if (dialogAnswer==kAEYes)
- myErr = SaveAskingName(aDocument, canInteract);
- else
- myErr = noErr; /* Don't save */
- }
-
- if (!myErr) {
- #ifndef RUNTIME
- if (aDocument->kind == kDocumentWindow && aDocument->u.reg.numSections)
- DeRegisterAllSections(aDocument);
- #endif
-
- CloseMyWindow(aWindow);
- }
- } else if (aDocument->u.cons.selected) {
- if (!gQuitting) {
- SysBeep(0);
-
- return userCanceledErr;
- }
- } else
- SaveConsole(aDocument);
- } else
- myErr = errAEIllegalIndex;
-
- return myErr;
- }
-
- #pragma segment File
-
- // DoQuit
- // saveOpt - one of kAEAsk,kAEYes,kAENo
- // if kAEYes or kAEAsk then AEInteactWithUser should have been called
- // before DoQuit. Assumes that it can interact if it needs to.
-
- pascal void DoQuit(DescType saveOpt)
- {
- WindowPeek aWindow;
- WindowPeek nextWindow;
- short theKind;
-
- if (gRunningPerl && (Alert(AbortAlert, nil) == 2))
- return;
-
- gQuitting = true;
-
- for (aWindow = (WindowPeek) FrontWindow(); aWindow; aWindow = nextWindow) {
- nextWindow = aWindow->nextWindow;
- if (Ours((WindowPtr) aWindow)) {
- if (DoClose((WindowPtr) aWindow, true, saveOpt)) {
- gQuitting = false;
-
- return;
- }
- } else {
- theKind = aWindow->windowKind;
- if (theKind < 0)
- CloseDeskAcc(theKind);
- }
- }
- }
-
- pascal Boolean GetFileFilter(ParmBlkPtr info)
- {
- switch (info->fileParam.ioFlFndrInfo.fdType) {
- case 'APPL':
- switch (info->fileParam.ioFlFndrInfo.fdCreator) {
- case MPRtSig:
- return false;
- case MPAppSig:
- return !info->fileParam.ioFlLgLen;
- default:
- return true;
- }
- case 'TEXT':
- return false;
- default:
- return true;
- }
- }
-
- pascal OSErr GetFile(FSSpec *theFSSpec)
- {
- #ifndef RUNTIME
-
- SFTypeList myTypes = {'TEXT', 'APPL'};
- StandardFileReply reply;
-
- StandardGetFile(GetFileFilter, 2, myTypes, &reply);
-
- if (reply.sfGood) {
- *theFSSpec = reply.sfFile;
- return noErr;
- } else
- return userCanceledErr;
-
- #else
-
- SFTypeList myTypes = {'TEXT', 'APPL'};
- SFReply reply;
- Point where;
-
- where.h = where.v = 75;
-
- SFGetFile(
- where, "\p",
- GetFileFilter, 2, myTypes,
- (DlgHookProcPtr) nil,
- &reply);
-
- if (reply.good)
- return WD2FSSpec(reply.vRefNum, reply.fName, theFSSpec);
- else
- return userCanceledErr;
-
- #endif
- }
-
- #pragma segment File
-
- pascal OSErr DoCreate(FSSpec theSpec)
- {
- OSErr err;
-
- #ifndef RUNTIME
- err = FSpCreate(&theSpec, MPAppSig, 'TEXT', smSystemScript);
- #else
- err = HCreate(theSpec.vRefNum, theSpec.parID, theSpec.name, MPAppSig, 'TEXT');
- #endif
-
- if (!err)
- HCreateResFile(theSpec.vRefNum, theSpec.parID, theSpec.name);
- else
- ShowError("\pCreating", err);
-
- return err;
- }
-
- pascal OSErr SaveConsole(DPtr doc)
- {
- OSErr err;
- short resFile;
- HHandle theHHandle;
- Str255 title;
- Boolean existing;
-
- if (gPrefsFile) {
- resFile = CurResFile();
- UseResFile(gPrefsFile);
- GetWTitle(doc->theWindow, title);
-
- if (theHHandle = (HHandle) Get1NamedResource('TFSS', title)) {
- existing = true;
- } else {
- existing = false;
- theHHandle = (HHandle)NewHandle(sizeof(HeaderRec));
- }
-
- HLock((Handle)theHHandle);
-
- (*theHHandle)->theRect = doc->theWindow->portRect;
- OffsetRect(
- &(*theHHandle)->theRect,
- -doc->theWindow->portBits.bounds.left,
- -doc->theWindow->portBits.bounds.top);
-
- GetFontName((*(doc->theText))->txFont, &(*theHHandle)->theFont);
-
- (*theHHandle)->theSize = (*(doc->theText))->txSize;
- (*theHHandle)->lastID = 0;
- (*theHHandle)->numSections = 0;
-
- HUnlock((Handle)theHHandle);
-
- if (existing) {
- ChangedResource((Handle) theHHandle);
- WriteResource((Handle) theHHandle);
- UpdateResFile(gPrefsFile);
- } else {
- AddResource((Handle)theHHandle, 'TFSS', Unique1ID('TFSS'), title);
- }
-
- err = ResError();
-
- UseResFile(resFile);
- }
-
- DoHideWindow(doc->theWindow);
- TESetSelect(0, 32767, doc->theText);
- TEDelete(doc->theText);
-
- if (doc->u.cons.fence < 32767)
- doc->u.cons.fence = 0;
-
- return err;
- }
-
- pascal void ApplySettings(DPtr doc, HPtr settings)
- {
- short fNum;
- FontInfo info;
- Rect bounds;
-
- GetFNum(settings->theFont, &fNum);
- SetPort(doc->theWindow);
- TextFont(fNum);
- TextSize(settings->theSize);
- GetFontInfo(&info);
-
- (*doc->theText)->txFont = fNum;
- (*doc->theText)->txSize = settings->theSize;
- (*doc->theText)->lineHeight = info.ascent+info.descent+info.leading;
- (*doc->theText)->fontAscent = info.ascent;
-
- bounds = settings->theRect;
- InsetRect(&bounds, 20, 20);
-
- if (settings->theRect.right > settings->theRect.left + 50 &&
- settings->theRect.bottom > settings->theRect.top + 50 &&
- RectInRgn(&bounds, GetGrayRgn())
- ) {
- MoveWindow(doc->theWindow, settings->theRect.left, settings->theRect.top, false);
- SizeWindow(
- doc->theWindow,
- settings->theRect.right - settings->theRect.left,
- settings->theRect.bottom - settings->theRect.top,
- false);
- }
-
- ResizeWindow(doc);
- }
-
- pascal void RestoreConsole(DPtr doc)
- {
- short resFile;
- HHandle theHHandle;
- Str255 title;
-
- if (!gPrefsFile)
- return;
-
- resFile = CurResFile();
- UseResFile(gPrefsFile);
- GetWTitle(doc->theWindow, title);
-
- if (theHHandle = (HHandle) Get1NamedResource('TFSS', title)) {
- HLock((Handle)theHHandle);
-
- ApplySettings(doc, *theHHandle);
-
- HUnlock((Handle)theHHandle);
- }
-
- UseResFile(resFile);
- }
-
-
- /** -----------------------------------------------------------------------
- Name: GetFileContents
- Purpose: Opens the document specified by theFSSpec and puts
- the contents into theDocument.
- -----------------------------------------------------------------------**/
-
- #pragma segment File
-
- pascal OSErr GetFileContents(FSSpec spec, DPtr theDocument)
- {
- long theSize;
- short oldRes;
- short resFile;
- short refNum;
- OSErr err;
- HHandle aHandle;
- Handle gHandle;
-
- oldRes = CurResFile();
- resFile = HOpenResFile(spec.vRefNum, spec.parID, spec.name, fsRdPerm);
-
- switch (theDocument->type) {
- case kOldRuntime6Doc:
- case kPlainTextDoc:
- #ifndef RUNTIME
- if (err = HOpenDF(spec.vRefNum, spec.parID, spec.name, fsRdPerm, &refNum)) {
- ShowError("\pread file - HOpenDF", err);
- #else
- if (err = HOpen(spec.vRefNum, spec.parID, spec.name, fsRdPerm, &refNum)) {
- ShowError("\pread file - HOpen", err);
- #endif
- refNum = 0;
-
- goto giveUp;
- }
-
- if (err = GetEOF(refNum, &theSize))
- goto giveUp;
-
- gHandle = NewHandle(theSize);
-
- HLock(gHandle);
- if (err = FSRead(refNum, &theSize, *gHandle))
- return err;
- HUnlock(gHandle);
- FSClose(refNum);
- break;
-
- giveUp:
- if (refNum)
- FSClose(refNum);
-
- if (resFile > -1)
- CloseResFile(resFile);
-
- UseResFile(oldRes);
-
- return err;
- default:
- gHandle = Get1NamedResource('TEXT', "\p!");
-
- if (gHandle)
- DetachResource(gHandle);
- else {
- err = ResError();
-
- goto giveUp;
- }
- break;
- }
-
- theDocument->u.reg.numSections = 0;
-
- if (resFile != -1) {
- aHandle = nil;
-
- if (Count1Resources('TFSS'))
- aHandle = (HHandle)Get1Resource('TFSS', 255);
-
- if (aHandle) {
- theDocument->u.reg.numSections = (*aHandle)->numSections;
-
- HLock((Handle) aHandle);
- ApplySettings(theDocument, *aHandle);
- }
-
- /*
- If there is a print record saved, ditch the old one
- created by new document and fill this one in
- */
- if (Count1Resources('TFSP')) {
- if (theDocument->thePrintSetup)
- DisposHandle((Handle)theDocument->thePrintSetup);
-
- theDocument->thePrintSetup = (THPrint)Get1Resource('TFSP', 255);
- HandToHand((Handle *)&theDocument->thePrintSetup);
-
- PrValidate(theDocument->thePrintSetup);
- }
-
- #ifndef RUNTIME
- if (theDocument->u.reg.numSections) {
- ReadSectionRecords(theDocument);
- ReadAllSectionResources(theDocument);
- }
- #else
- theDocument->u.reg.numSections = 0;
- #endif
-
- CloseResFile(resFile);
-
- if (err = ResError()) {
- ShowError("\pread file- CloseResFile", err);
- return err;
- }
- }
-
- HLock(gHandle);
- if (GetHandleSize(gHandle) > 32000) {
- PtrToXHand(
- *gHandle,
- (*theDocument->theText)->hText,
- GetHandleSize(gHandle));
-
- err = elvisErr;
- } else
- TESetText(*gHandle, GetHandleSize(gHandle), theDocument->theText);
- DisposHandle(gHandle);
-
- if (err == fnfErr)
- return noErr;
- else
- return err;
- } /* GetFileContents */
-
-
- #pragma segment File
-
- pascal OSErr SaveAskingName(DPtr aDocument, Boolean canInteract)
- {
- OSErr myErr;
-
- if (aDocument->kind != kDocumentWindow || !aDocument->u.reg.everSaved) {
-
- if (canInteract) {
- if (myErr = GetFileNameToSaveAs(aDocument))
- return myErr;
-
- if (myErr = DoSave(aDocument, aDocument->theFSSpec))
- return myErr;
-
- #ifndef RUNTIME
- AssocAllSections(aDocument);
- #endif
-
- return noErr;
- } else
- return errAENoUserInteraction;
-
- } else
- return SaveUsingTemp(aDocument);
- }
-
- #pragma segment File
-
- pascal OSErr SaveUsingTemp(DPtr theDocument)
- {
- Str255 tempName;
- OSErr err;
- FSSpec tempFSSpec;
-
- /*save the file to disk using a temporary file*/
- /*this is the recommended way of doing things*/
- /*first write out the file to disk using a temporary filename*/
- /*if it is sucessfully written, exchange the temporary file with the last one saved*/
- /*then delete the temporary file- so if anything goes wrong, the original version is still there*/
- /*first generate the temporary filename*/
-
- GetTempFileName(theDocument, &tempName);
- /*create this file on disk*/
-
- tempFSSpec = theDocument->theFSSpec;
- PLstrcpy(tempFSSpec.name, tempName);
-
- if (err = DoCreate(tempFSSpec))
- return err;
-
- if (err = DoSave(theDocument, tempFSSpec))
- return err;
-
- #ifndef RUNTIME
- if (err = FSpExchangeFiles(&tempFSSpec, &theDocument->theFSSpec))
- return err;
-
- /*we've exchanged the files, now delete the temporary one*/
-
- err = FSpDelete(&tempFSSpec);
- #else
- err = FSpSmartMove(&tempFSSpec, &theDocument->theFSSpec);
- #endif
-
- if (!err)
- theDocument->dirty = false;
-
- return err;
- }
-
-
- #pragma segment File
-
- pascal short SaveScriptHook(short item, DialogPtr dlg, void * params)
- {
- short kind;
- ControlHandle type;
- Rect r;
- DPtr doc = (DPtr) params;
-
- if (GetWRefCon(dlg) != 'stdf')
- return item;
-
- switch (item) {
- case sfHookFirstCall:
- GetDItem(dlg, ssd_Type, &kind, (Handle *) &type, &r);
- SetCtlValue(type, doc->type);
-
- return sfHookFirstCall;
- case ssd_Type:
- GetDItem(dlg, item, &kind, (Handle *) &type, &r);
-
- doc->type = (DocType) GetCtlValue(type);
-
- return sfHookNullEvent;
- default:
- return item;
- }
- }
-
- /*
- Fills in the document record with the user chosen destination
- */
-
- pascal OSErr GetFileNameToSaveAs(DPtr theDocument)
- {
- #ifndef RUNTIME
- OSErr err;
- StandardFileReply reply;
- Str255 suggestName;
- Point where;
-
- where.h = where.v = -1;
-
- GetWTitle(theDocument->theWindow, suggestName);
-
- CustomPutFile(
- "\pSave Document As:", suggestName, &reply,
- SaveScriptDialog,
- where,
- SaveScriptHook,
- (ModalFilterYDProcPtr) nil,
- nil,
- (ActivateYDProcPtr) nil,
- theDocument);
-
- if (reply.sfGood)
- switch (err = FSpDelete(&reply.sfFile)) {
- case noErr:
- case fnfErr:
- theDocument->theFSSpec = reply.sfFile;
- PLstrcpy(theDocument->theFileName, reply.sfFile.name);
-
- return noErr;
- default:
- return err;
- }
- else
- return userCanceledErr;
- #else
- OSErr err;
- SFReply reply;
- Str255 suggestName;
- Point where;
-
- where.h = where.v = 75;
-
- GetWTitle(theDocument->theWindow, suggestName);
-
- SFPutFile(
- where, "\pSave Document As:",
- suggestName, (DlgHookProcPtr) nil,
- &reply);
-
- if (reply.good) {
- FSSpec spec;
-
- if (err = WD2FSSpec(reply.vRefNum, reply.fName, &spec))
- return err;
- switch (err = HDelete(spec.vRefNum, spec.parID, spec.name)) {
- case noErr:
- case fnfErr:
- theDocument->theFSSpec = spec;
- PLstrcpy(theDocument->theFileName, spec.name);
-
- return noErr;
- default:
- return err;
- }
- } else
- return userCanceledErr;
- #endif
- } /* GetFileNameToSaveAs */
-
- #pragma segment File
-
- pascal OSErr OpenOld(FSSpec aFSSpec, DocType type)
- {
- DPtr theDocument;
- OSErr fileErr;
-
- theDocument = NewDocument(true, kDocumentWindow);
-
- SetWTitle(theDocument->theWindow, aFSSpec.name);
-
- SetPort(theDocument->theWindow);
-
- theDocument->theFSSpec = aFSSpec;
-
- PLstrcpy(theDocument->theFileName,aFSSpec.name);
-
- theDocument->dirty = false;
- #ifndef RUNTIME
- theDocument->type = (type == kOldRuntime6Doc) ? kRuntime6Doc : type;
- theDocument->u.reg.everSaved = (type != kOldRuntime6Doc);
- #else
- theDocument->type = kPlainTextDoc;
- theDocument->u.reg.everSaved = (type == kPlainTextDoc);
- #endif
-
- fileErr = GetFileContents(aFSSpec, theDocument);
-
- if (!fileErr) {
- ResizeWindow(theDocument);
- DoShowWindow(theDocument->theWindow);
- } else {
- if (fileErr == elvisErr) {
- theDocument->u.reg.everSaved = false;
- #ifdef RUNTIME
- if (AEInteractWithUser(kAEDefaultTimeout, nil, nil))
- #endif
- if (Alert(ElvisAlert, nil) == 1)
- SaveAskingName(theDocument, true);
- } else
- FileError("\pError Opening ", aFSSpec.name);
-
- CloseMyWindow(theDocument->theWindow);
- }
-
- return fileErr;
- } /* OpenOld */
-
- pascal DocType GetDocType(FSSpec * spec)
- {
- CInfoPBRec info;
- DocType type = kUnknownDoc;
- short resFile;
- short nuFile;
- OSType ** rtType;
-
- if (FSpCatInfo(spec, &info))
- return kUnknownDoc;
-
- switch (info.hFileInfo.ioFlFndrInfo.fdType) {
- case 'APPL':
- switch (info.hFileInfo.ioFlFndrInfo.fdCreator) {
- case MPRtSig:
- resFile = CurResFile();
- nuFile = HOpenResFile(spec->vRefNum, spec->parID, spec->name, fsRdPerm);
-
- if (nuFile != -1) {
- if (rtType = (OSType **) Get1Resource('MrPL', 128))
- switch (**rtType) {
- case 'SCPT':
- type = kScriptDoc;
- break;
- case 'MrP7':
- type = kRuntime7Doc;
- break;
- case 'MrP6':
- type = kRuntime6Doc;
- break;
- }
-
- CloseResFile(nuFile);
- }
- UseResFile(resFile);
-
- return type;
- case MPAppSig:
- /* A heuristic to separate old runtimes from PowerPC executables */
- if (info.hFileInfo.ioFlLgLen && info.hFileInfo.ioFlLgLen < 100000)
- return kOldRuntime6Doc;
- /* Fall through */
- default:
- return kUnknownDoc;
- }
- case 'TEXT':
- return kPlainTextDoc;
- case 'pref':
- switch (info.hFileInfo.ioFlFndrInfo.fdCreator) {
- case MPAppSig:
- case MPRtSig:
- return kPreferenceDoc;
- }
- /* Fall through */
- default:
- return kUnknownDoc;
- }
- }